﻿using System.Collections.Generic;
using UnityEngine;
using Yoozoo.Core.Extensions.CSharp;

namespace Yoozoo.Modules.Furnitures
{
    /// <summary>
    /// 用于生成房间的定义脚本
    /// </summary>
    public class Room : MonoBehaviour
    {
        public int RoomId;

        [Tooltip("房间高度, 影响到墙的高度")]
        public float Height = 3;

        [Tooltip("默认墙纸的家具ID")]
        public int WallpaperId = 0;

        [Tooltip("默认地砖的家具ID")]
        public int FloorTileId = 0;

        public List<Plane> Planes = new List<Plane>();

        public int SelectedPlaneIndex = 0;

        public RoomSceneConfig RoomSceneConfig = new RoomSceneConfig();

        public Plane GetSelectedPlane()
        {
            if (Planes.IsEmpty())
            {
                return null;
            }

            if (SelectedPlaneIndex < 0 || SelectedPlaneIndex >= Planes.Count)
            {
                return null;
            }

            return Planes[SelectedPlaneIndex];
        }

        /// <summary>
        /// 删除选中的平面 (不能删除地面)
        /// </summary>
        public void RemoveSelectedPlane()
        {
            if (Planes.IsEmpty())
            {
                return;
            }

            if (SelectedPlaneIndex <= 0 || SelectedPlaneIndex >= Planes.Count)
            {
                return;
            }

            Planes.RemoveAt(SelectedPlaneIndex);
            if (SelectedPlaneIndex >= Planes.Count)
            {
                SelectedPlaneIndex = Planes.Count - 1;
            }
        }

        public void MakeWalls()
        {
            if (Planes.IsEmpty())
            {
                return;
            }

            var polygon = Planes[0].Polygon;
            if (polygon.IsEmpty() || polygon.Count < 3)
            {
                return;
            }

            // 这里要假设多边形的点是顺时针排列的
            //  p2 ------------ p3
            //  |               |
            //  p1              | 
            //    \ - p0 ------ p4

            for (int i = 0; i < polygon.Count; i++)
            {
                // 以p0, p1为例， 生成的墙面如下
                //              ↑ z轴
                //              ↑
                //              ↑
                //       q1 --- q0
                //       |      |       y轴
                //       |      |     ↗ 
                //       |      |   ↗
                //       |      | ↗
                // ←←← p1 --- p0
                // x轴
                // currentPoint = p0, nextPoint = p1
                // 因为要满足左手定则， 并且各个轴向的要求，所以原点需要设在p0

                var go = new GameObject("Wall");
                go.transform.SetParent(transform);

                var plane = new Plane();
                plane.OriginPoint = go.transform;

                var currentPoint = polygon[i];
                var nextPoint = i == polygon.Count - 1 ? polygon[0] : polygon[i + 1];
                go.transform.position = currentPoint;

                plane.Length = Mathf.CeilToInt(Vector3.Distance(currentPoint, nextPoint));
                plane.Width = Mathf.CeilToInt(Height);
                plane.PlaneType = PlaneType.Wall;

                //var p = new UnityEngine.Plane(polygon[i], go.transform.position, nextPoint);
                //Quaternion rotation = Quaternion.LookRotation((nextPoint - polygon[i]), Vector3.forward);
                var x = nextPoint - currentPoint;
                var z = Vector3.up;
                var y = Vector3.Cross(z, x);

                Quaternion rotation = Quaternion.LookRotation(z, y);
                go.transform.rotation = rotation;

                Planes.Add(plane);
            }
        }

        void OnDrawGizmos()
        {
            if (Planes == null)
                return;

            var color = Gizmos.color;
            Gizmos.color = Color.red;
            var plane = GetSelectedPlane();
            if (plane != null)
            {
                var origin = plane.OriginCoordinate;
                var axisX = plane.AxisX;
                var axisY = plane.AxisY;

                for (int x = 0; x <= plane.Length * 2; x++)
                {
                    Gizmos.DrawLine(origin + axisX * x * 0.5f, origin + axisX * x * 0.5f + axisY * plane.Width);
                }

                for (int y = 0; y <= plane.Width * 2; y++)
                {
                    Gizmos.DrawLine(origin + axisY * y * 0.5f, origin + axisY * y * 0.5f + axisX * plane.Length);
                }

                Gizmos.color = Color.yellow;
                int length = plane.Polygon.Count;
                for (int i = 0; i < length; i++)
                {
                    Gizmos.DrawSphere(plane.GetPointInWorld(i), 0.2f);
                }

                for (int i = 0; i < length - 1; i++)
                {
                    Gizmos.DrawLine(plane.GetPointInWorld(i), plane.GetPointInWorld(i +1));
                }

                if (length >= 3)
                {
                    Gizmos.DrawLine(plane.GetPointInWorld(length - 1), plane.GetPointInWorld(0));
                }
            }

            Gizmos.color = color;
        }

        /// <summary>
        /// 复制平面
        /// </summary>
        /// <param name="plane"></param>
        public void Copy(Plane plane)
        {
            var copy = new Plane();
            var originPoint = plane.OriginPoint;
            if (originPoint)
            {
                var go = new GameObject("Copy of " + originPoint.name);
                go.transform.SetParent(originPoint.parent);
                go.transform.position = originPoint.position;
                go.transform.rotation = originPoint.rotation;
                go.transform.localScale = Vector3.one;
                copy.OriginPoint = go.transform;
            }

            copy.Length = plane.Length;
            copy.Width = plane.Width;
            copy.PlaneType = plane.PlaneType;
            copy.Polygon.AddRange(plane.Polygon);

            Planes.Add(copy);
        }

        /// <summary>
        /// 创建平面
        /// </summary>
        public void CreatePlane()
        {
            var plane = new Plane();

            var go = new GameObject("Plane");
            go.transform.SetParent(transform);
            go.transform.localPosition = new Vector3(-15, 0, -15);
            go.transform.localEulerAngles = Vector3.zero;
            go.transform.localScale = Vector3.one;
            plane.OriginPoint = go.transform;

            plane.Length = 30;
            plane.Width = 30;
            plane.PlaneType = PlaneType.Floor;

            Planes.Add(plane);
        }

        public void ApplySceneConfig()
        {
            RoomSceneConfig.LoadAssets((() =>
            {
                RoomSceneConfig.ApplySetting(transform.parent);
                RoomSceneConfig.FixMeshRenderers(transform.parent);
            }));
        }
        
        public void FixMeshRenderers()
        {
            RoomSceneConfig.FixMeshRenderers(transform.parent);
        }
            
    }
}
